package com.hengpeng.common.scheduling.quartz;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.NthIncludedDayTrigger;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;

import com.hengpeng.common.scheduling.Command;
import com.hengpeng.common.scheduling.ScheduleConfig;
import com.hengpeng.common.scheduling.TimeIterator;

/**
 * <pre>
 * 定时作业调度框架
 * </pre>
 * @author chenhui
 * @version 1.0, 2013-1-5
 */
public class QuartzSchedule
{
	private static final Log logger = LogFactory.getLog(QuartzSchedule.class);

	private ScheduleConfig scheduleconfig;

	private Scheduler scheduler;

	public QuartzSchedule(ScheduleConfig config, Scheduler scheduler)
	{
		this.scheduleconfig = config;
		this.scheduler = scheduler;
	}

	public void start(Map<String, List<String>> triggerMap)
	{
		try
		{
			JobDetail jobDetail = new JobDetail();
			jobDetail.setName(scheduleconfig.getName());
			Command command = (Command) Class.forName(scheduleconfig.getClassImpl()).newInstance();
			jobDetail.getJobDataMap().put("command", command);
			jobDetail.getJobDataMap().put("config", scheduleconfig);
			// 单例启动作业
			if (scheduleconfig.isSingleton())
			{
				jobDetail.setJobClass(CommandJobBean.class);
			}
			else
			{
				jobDetail.setJobClass(SingleTonCommandJobBean.class);
			}
			scheduler.addJob(jobDetail, true);
			List<String> trigerList = new ArrayList<String>();
			createSchedule(trigerList);
			if (triggerMap.containsKey(scheduleconfig.getName()))
			{
				triggerMap.get(scheduleconfig.getName()).addAll(trigerList);
			}
			else
			{
				triggerMap.put(scheduleconfig.getName(), trigerList);
			}
			logger.info("定时作业启动成功{" + scheduleconfig.getName() + "}");
		}
		catch (Exception e)
		{
			logger.error("启动定时作业失败{" + scheduleconfig.getName() + "," + scheduleconfig.getClassImpl() + "}", e);
		}
	}

	private void createSchedule(List<String> trigerList)
	{
		try
		{

			String triggername = "";
			TimeIterator[] timeiterator = scheduleconfig.getIterator();
			Calendar now = Calendar.getInstance(TimeZone.getDefault());
			Date start = new Date(now.getTimeInMillis() + 10000L);
			for (int i = 0; i < timeiterator.length; i++)
			{
				int triggerNum = 0;
				TimeIterator iterator2 = timeiterator[i];
				String[] dayTimes = iterator2.getDaytimes();
				switch (iterator2.getRepeatMode())
				{
					case -1:// 任务不执行
						break;

					case Calendar.MILLISECOND:// 按千分之妙进行迭代
						triggername = "trigger_" + scheduleconfig.getName() + i;
						Trigger secondTrigger = new SimpleTrigger(triggername, null, scheduleconfig.getName(),
								Scheduler.DEFAULT_GROUP, start, null, SimpleTrigger.REPEAT_INDEFINITELY,
								iterator2.getInterval());
						scheduler.scheduleJob(secondTrigger);
						trigerList.add(triggername);
						break;

					case Calendar.MINUTE: // 按分钟进行迭代
						triggername = "trigger_" + scheduleconfig.getName() + i;
						long min = 60L * 1000L;
						Trigger minTrigger = new SimpleTrigger(triggername, null, scheduleconfig.getName(),
								Scheduler.DEFAULT_GROUP, start, null, SimpleTrigger.REPEAT_INDEFINITELY,
								iterator2.getInterval() * min);
						scheduler.scheduleJob(minTrigger);
						trigerList.add(triggername);
						break;

					case Calendar.DAY_OF_MONTH:// 按天进行迭代
						for (String time : dayTimes)
						{
							triggerNum++;
							triggername = "trigger_" + scheduleconfig.getName() + i + "_" + triggerNum;
							String[] times = time.split(":");
							if (times.length != 3)
							{
								throw new Exception("时间格式错误{" + time + "},任务{" + scheduleconfig.getName() + "}");
							}
							CronTrigger trigger = new CronTrigger(triggername, Scheduler.DEFAULT_GROUP,
									scheduleconfig.getName(), Scheduler.DEFAULT_GROUP);
							String exp = Integer.parseInt(times[2]) + " " + Integer.parseInt(times[1]) + " "
									+ Integer.parseInt(times[0]) + " * * ?";
							trigger.setCronExpression(exp);
							scheduler.scheduleJob(trigger);
							trigerList.add(triggername);
						}
						break;

					case Calendar.MONTH:// 按月迭代
						for (int daynum : iterator2.getMonthdays())
						{
							for (String string : dayTimes)
							{
								triggerNum++;
								triggername = "trigger_" + scheduleconfig.getName() + i + "_" + triggerNum;
								NthIncludedDayTrigger ntrigger = new NthIncludedDayTrigger(triggername,
										Scheduler.DEFAULT_GROUP, scheduleconfig.getName(), Scheduler.DEFAULT_GROUP);
								ntrigger.setIntervalType(NthIncludedDayTrigger.INTERVAL_TYPE_MONTHLY);
								ntrigger.setFireAtTime(string);
								ntrigger.setN(daynum);
								scheduler.scheduleJob(ntrigger);
								trigerList.add(triggername);
							}
						}
						break;

					case Calendar.DAY_OF_WEEK:// 默认按星期进行迭代
						for (int daynum : iterator2.getWeekdays())
						{
							for (String string : dayTimes)
							{
								triggerNum++;
								triggername = "trigger_" + scheduleconfig.getName() + i + "_" + triggerNum;
								NthIncludedDayTrigger ntrigger = new NthIncludedDayTrigger(triggername,
										Scheduler.DEFAULT_GROUP, scheduleconfig.getName(), Scheduler.DEFAULT_GROUP);
								ntrigger.setIntervalType(NthIncludedDayTrigger.INTERVAL_TYPE_WEEKLY);
								ntrigger.setFireAtTime(string);
								switch (daynum)
								{
									case 1:// 周一
										ntrigger.setN(Calendar.MONDAY);
										break;
									case 2:// 周二
										ntrigger.setN(Calendar.TUESDAY);
										break;
									case 3:// 周三
										ntrigger.setN(Calendar.WEDNESDAY);
										break;
									case 4:// 周四
										ntrigger.setN(Calendar.THURSDAY);
										break;
									case 5:// 周五
										ntrigger.setN(Calendar.FRIDAY);
										break;
									case 6:// 周六
										ntrigger.setN(Calendar.SATURDAY);
										break;
									case 7:// 周天
										ntrigger.setN(Calendar.SUNDAY);
										break;
								}
								scheduler.scheduleJob(ntrigger);
								trigerList.add(triggername);
							}
						}
						break;
				}
			}
		}
		catch (Exception e)
		{
			logger.error("任务调度设置触发trigger失败:" + scheduleconfig.getName(), e);
		}
	}
}
